package com.letv.download.cpinfo;

import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.letv.common.ConnectionManager;
import com.letv.common.Constants;
import com.letv.conf.ConfigFactory;
import com.letv.download.DownloadUtils;
import com.letv.util.SQLUtil;

/**
 * download cp info from cms
 */
public class CpInfoDataDonwload {

    /**
     * String, thread pool base size path in config file
     */
    private static final String POOL_SIZE_PATH = "threadPool.basesize";

    /**
     * String, thread pool base size.program will use it when this parameter does't exist in config file
     */
    private static final int POOL_SIZE = 10;

    /**
     * String, the number of each thread will download in config file
     */
    private static final String PAGE_SIZE_PATH = "thread.pageSize";

    /**
     * String, the number of each thread will download.program will use it when this parameter does't exist in config file
     */
    private static final int PAGE_SIZE = 1000;

    /**
     * Logger
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(CpInfoDataDonwload.class);

    /**
     * DownloadUtils, common method for download data from cms
     */
    private DownloadUtils downloadUtils = new DownloadUtils();

    /**
     * download cp info from cms
     * now just copy table:
     * so_web_video_new/cp_info --> search2/cp_info
     */
    public void download() {
        Connection connectionFromLocal = null;
        try {
            ConnectionManager connectionManager = ConnectionManager.getInstance();
            connectionFromLocal = connectionManager.getConnection();
        } catch (Exception e) {
            LOGGER.error("cp_info fail to get id range,connection get connectionFromLeso error!", e);
            return;
        }

        try {
            if(!this.downloadUtils.copyTable(connectionFromLocal, Constants.CP_INFO_TB, Constants.CP_INFO_OLD_TB)) {
                LOGGER.error("fail to copy " + Constants.CP_INFO_TB + " " + Constants.CP_INFO_OLD_TB + ".");
                return;
            }
        } catch(Exception e) {
            LOGGER.error("error to copy cp table to old table", e);
        }  finally{
            if(!SQLUtil.close(connectionFromLocal)) {
                LOGGER.error("fail to close connectionFromLocal");
            }
        }

        List<Integer> idRangeList = this.downloadUtils.getIdRangeList();
        if(null == idRangeList) {
            LOGGER.error("fail to get id range of cp");
            return;
        }
        this.downloadByThreadPool(idRangeList.get(0).intValue() - 1, idRangeList.get(1).intValue());
    }

    /**
     * process cp info by thread pool between id range
     * @param beginId
     * @param endId
     */
    private void downloadByThreadPool(int beginId, int endId) {
        if(endId <= beginId) {
            LOGGER.error("cp_info fail to download by thread pool,method processInThreadPool gets illegal arguments");
            return;
        }
        LOGGER.info("cp info begin to download by thread pool,beginId=" + beginId + ",endId=" + endId);

        ExecutorService threadPool = null;
        try {
            threadPool = Executors.newFixedThreadPool(ConfigFactory.getInt(CpInfoDataDonwload.POOL_SIZE_PATH, CpInfoDataDonwload.POOL_SIZE));
        } catch(Exception e) {
            LOGGER.error("cp_info fail to download by thread pool,fail to create thread pool");
            return;
        }

        int pageSize = 0;
        int totalWorkerCount = 0;
        try {
            pageSize = ConfigFactory.getInt(CpInfoDataDonwload.PAGE_SIZE_PATH, CpInfoDataDonwload.PAGE_SIZE);
            totalWorkerCount = (endId - beginId) / pageSize + 1;
        } catch(Exception e) {
            LOGGER.error("cp_info fail to download by thread pool,fail to set pageSize or calculate totalPageCount");
            return;
        }
        LOGGER.info("each worker download " + pageSize + " data,total need " + totalWorkerCount + " workers");

        List<CpInfoDataDownloadWorker> workerList = null;
        try {
            workerList = new ArrayList<CpInfoDataDownloadWorker>();
            for(int i = 1; i <= totalWorkerCount; i++) {
                workerList.add(new CpInfoDataDownloadWorker(i-1, beginId + pageSize * (i - 1), beginId + pageSize * i));
            }
        } catch(Exception e) {
            LOGGER.error("cp_info fail to process by thread pool,fail to create process worker list");
            return;
        }

        try {
            threadPool.invokeAll(workerList);
        } catch (Exception e) {
            LOGGER.error("cp_info fail to download by thread pool,fail to invoke thread list", e);
        } finally {
            threadPool.shutdown();
            LOGGER.info("download cp_info 's threadPool shutdown!");
        }
    }
}
